package main
 
import (
	"bytes"
	"crypto/aes"
	"crypto/sha1"
	"encoding/hex"
    "encoding/base64"
	"errors"
	"strings"
    "fmt"
	"os"
)

func main() {
	if len(os.Args) <= 1 {
	    fmt.Println(fmt.Sprintf("USAGE %s <INPUT>", os.Args[0]))
		os.Exit(0)
	}

	key := "ff2f10b642ad44aca3c49f8a16c526f4ff2f"
//    input := AesEncrypt([]byte("13585587064"), key)
//	inputBin,_ := hex.DecodeString(input)
//    encodeString := base64.StdEncoding.EncodeToString(inputBin)
//    fmt.Println(encodeString)

    // "UCqoE/ZAvNVuu8lA38LVaygdtrJ8Gq+KmqWDdvhgxS8="
	encodeString := os.Args[1]
	decodeBytes, err := base64.StdEncoding.DecodeString(encodeString)
	if err != nil {
	    fmt.Println(err)
	}
	str := hex.EncodeToString(decodeBytes)
//  fmt.Println(str)

	de := AesDecrypt(str, key)
	decodeRlt,_ := base64.StdEncoding.DecodeString(de)
	output := string(decodeRlt)
    fmt.Println(output)
}

func AesDecrypt(data, outEncryptKey string) string {
	dataByte := Hex2bin(data)
	key, err := AesSha1prng([]byte(outEncryptKey), 128)
	if err != nil {
		return ""
	}

	block, err := aes.NewCipher(generateKey(key))
	if err != nil {
		return ""
	}

	decrypted := make([]byte, len(dataByte))
	size := block.BlockSize()
	for bs, be := 0, size; bs < len(dataByte); bs, be = bs+size, be+size {
		block.Decrypt(decrypted[bs:be], dataByte[bs:be])
	}

	decrypted = PKCS5UnPadding(decrypted)
	return string(decrypted)
}

func AesEncrypt(data []byte, outEncryptKey string) string {
	key, err := AesSha1prng([]byte(outEncryptKey), 128)
	if err != nil {
		return ""
	}

	block, err := aes.NewCipher(generateKey(key))
	if err != nil {
		return ""
	}

	data = PKCS5Padding(data, block.BlockSize())
	decrypted := make([]byte, len(data))
	size := block.BlockSize()
	for bs, be := 0, size; bs < len(data); bs, be = bs+size, be+size {
		block.Encrypt(decrypted[bs:be], data[bs:be])
	}

	return Bin2hex(decrypted)
}

func AesSha1prng(keyBytes []byte, encryptLength int) ([]byte, error) {
	hashs := Sha1(Sha1(keyBytes))
	maxLen := len(hashs)
	realLen := encryptLength / 8
	if realLen > maxLen {
		return nil, errors.New("invalid length")
	}

	return hashs[0:realLen], nil
}
 
func Sha1(data []byte) []byte {
	h := sha1.New()
	h.Write(data)
	bs := h.Sum(nil)
	h.Reset()

	return bs
}
 
func generateKey(key []byte) (genKey []byte) {
	genKey = make([]byte, 16)
	copy(genKey, key)
	for i := 16; i < len(key); {
		for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
			genKey[j] ^= key[i]
		}
	}
	return genKey
}
 
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

func Bin2hex(b []byte) string {
	hexStringData := strings.ToUpper(hex.EncodeToString(b))
	return hexStringData
}
func Hex2bin(x string) []byte {
	hexData, _ := hex.DecodeString(x)
	return hexData
}
